package com.mrdeer.iot.handler;

import com.mrdeer.iot.bean.ChannelInfo;
import com.mrdeer.iot.bean.command.Protocol;
import com.mrdeer.iot.constant.DriverContext;
import com.mrdeer.iot.entity.DeviceEntity;
import com.mrdeer.iot.service.DeviceService;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelId;
import io.netty.channel.ChannelInboundHandlerAdapter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;

/**
 * 链路管理
 *
 * @Author: xie jianchu
 */
@Slf4j
@Component
@ChannelHandler.Sharable
public class ChannelManagerHandler extends ChannelInboundHandlerAdapter {

    @Resource
    private DeviceService deviceService;

    @Override
    public void channelRegistered(ChannelHandlerContext ctx) throws Exception {
        log.info("new channel coming ---> {}", ctx.channel().id());
        ChannelId channelId = ctx.channel().id();
        ChannelInfo channelInfo = DriverContext.CHANNEL_INFO_MAP.getOrDefault(channelId, ChannelInfo.build("" + ctx.channel().id(), channelId, ctx.channel()));
        DriverContext.CHANNEL_INFO_MAP.put(channelId, channelInfo);
        ctx.fireChannelRegistered();
    }

    @Override
    public void channelUnregistered(ChannelHandlerContext ctx) throws Exception {
        log.info("channel out !---> {}", ctx.channel());
        ChannelId channelId = ctx.channel().id();
        ChannelInfo channelInfo = DriverContext.CHANNEL_INFO_MAP.remove(channelId);
        DriverContext.SN_CHANNEL_INFO_MAP.remove(channelInfo.getSn());
        log.info("remove channel:{}", channelInfo);
        DeviceEntity deviceEntity = deviceService.selectDeviceEntityByName(channelInfo.getSn());
        if (deviceEntity != null) {
            deviceEntity.setStatus(0);
            deviceService.update(deviceEntity);
        }
        ctx.fireChannelUnregistered();
    }

    /**
     * 补全 链路信息：根据 channelId 获取 channelInfo 并写入 sn 和 物联网信息
     *
     * @param ctx
     * @param sn
     */
    public static void setRTUChannelInfo(ChannelHandlerContext ctx, Protocol protocol, String sn) {
        ChannelId channelId = ctx.channel().id();
        DriverContext.CHANNEL_INFO_MAP.get(channelId)
                .setSn(channelId.asShortText()).setProtocol(protocol).setChannel(ctx.channel());
        ChannelInfo channelInfo = DriverContext.CHANNEL_INFO_MAP.get(channelId);
        DriverContext.SN_CHANNEL_INFO_MAP.put(sn, channelInfo);
        log.info("sn:{} in the house.", sn);
    }

    /**
     * 刷新链路信息
     */
    public static void refreshRTUChannelInfo() {
        log.info("refresh GlobalInfo...");
        DriverContext.CHANNEL_INFO_MAP.forEach(((channelId, channelInfo) -> {
            String sn = channelInfo.getSn();
            channelInfo.setProtocol(null);
        }));
        DriverContext.SN_CHANNEL_INFO_MAP.forEach((sn, channelInfo) -> channelInfo.setProtocol(null));
    }
}
